home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr48 / ned100.zip / COLORS.ASC < prev    next >
Text File  |  1993-04-08  |  14KB  |  300 lines

  1. Turbo Vision Palettes
  2.  
  3. Objects in Turbo Vision can be grouped into two broad classes: those which are
  4. descendants of TView (such as TWindow or TButton), and those which are not
  5. (such as TCollection). The difference, of course, is that objects which are
  6. descended from TView (also called "views" or "view objects") are intended to
  7. be displayed on the computer's screen at some point in their lifetimes. Every
  8. descendant of TView contains a Draw method, which is executed whenever the
  9. view needs to redraw itself. Although every view's Draw method is different,
  10. they all share one characteristic: they call GetColor to determine what
  11. on-screen colors to use when drawing the various parts of the view.
  12.  
  13. GetColor in turn calls GetPalette, which returns a pointer to the view's
  14. palette. What is a palette? In Turbo Vision, a palette acts as a translation
  15. table. In much the same way that the ASCII code maps byte values onto
  16. characters, a view's palette maps the set of colors used by the view onto the
  17. palette of the view's owner.
  18.  
  19. Let's look at the palette of the TLabel view as an example. (It's shown at the
  20. end of the description of TLabel in the Turbo Vision Guide.) We see that the
  21. palette has four entries, numbered 1 through 4. TLabel's Draw method knows
  22. that when it wants to draw normal text, it should use color number 1. But it
  23. doesn't know what color number 1 really is, and it doesn't care. It simply
  24. calls GetColor (1) and uses the color that GetColor returns.
  25.  
  26. GetColor calls GetPalette, which returns a pointer to TLabel's palette. From
  27. the values contained in the palette, GetColor determines that for TLabel,
  28. color number 1 is equivalent to TLabel's owner's color number 7. GetColor then
  29. calls Owner^.GetColor (7); the owner view then goes through the same
  30. procedure, using its own palette to perform another level of translation, and
  31. so on, until the ultimate owner is reached, which in most Turbo Vision
  32. programs is a TApplication object (or descendant). The TApplication object is
  33. the final color arbiter, and provides all of the views with the actual video
  34. attributes to use.
  35.  
  36. Let's trace through the TLabel color hierarchy: We've already determined that
  37. TLabel color number 1 maps onto its owner's color number 7. The description of
  38. TLabel's palette in the TV Guide states that TLabel's palette maps onto the
  39. standard dialog palette. This tells us that TLabel objects are intended to be
  40. owned by (i.e., inserted into) TDialog objects. If we now turn to TDialog's
  41. palette description, we see that color number 7 (called "Label Normal") is
  42. mapped onto TDialog's owner's color number 38. Well, dialog boxes are usually
  43. inserted into the desktop, so let's look at TDeskTop's palette. When we do
  44. that, we see that TDeskTop doesn't have a palette; this means that TDeskTop
  45. doesn't do any color translation--TDialog's color number 38 "falls through" to
  46. TDeskTop's owner's palette. Well, the desktop is owned by the application, so
  47. we've reached the end of the chain. When TLabel's Draw method wants to use
  48. color number 1, it eventually gets told to use the application's color number
  49. 38.
  50.  
  51. TApplication's palettes are not shown in the TV Guide, but we can find them in
  52. the file APP.PAS in the TVISION directory. TApplication actually uses one of
  53. three different palettes, depending on whether the program is being run on a
  54. color, black and white, or monochrome monitor. For the purposes of this
  55. example, we'll assume that we're using a color monitor. If we locate the 38th
  56. entry in TApplication's palette, we find that it is equal to $70. The upper
  57. nybble of the byte gives the background color, and the lower nybble the
  58. foreground color, according to the following table:
  59.  
  60.   0 - black         4 - red           8 - dark gray     C - light red
  61.   1 - blue          5 - magenta       9 - light blue    D - light magenta
  62.   2 - green         6 - brown         A - light green   E - yellow
  63.   3 - cyan          7 - light gray    B - light cyan    F - white
  64.  
  65. So, we see that a normal label has black text on a light gray background. All
  66. of the other colors may be tracked down in a similar manner.
  67.  
  68. What happens if rather than inserting a TLabel into a TDialog, we insert it
  69. into a TWindow? Well, let's follow the mapping, again using the "Normal Text"
  70. color: TLabel color number 1 -> TWindow color number 7 -> TApplication color
  71. number 14, 22, or 30, depending on whether the window is a blue, cyan, or gray
  72. window, respectively. These entries correspond to blue text on gray, blue text
  73. on green, or white text on light gray. Obviously, none of these are the same
  74. as the black text on light gray of a TLabel inserted into a TDialog. This
  75. points out a universal truth of Turbo Vision palettes: If a view is designed
  76. to be inserted into a particular type of owner view, inserting it into a
  77. different type of owner will almost always result in a change in color.
  78.  
  79. Anyone who has played around much with Turbo Vision has encountered the
  80. situation where a view is displayed in flashing white text on a red
  81. background. This happens when a call to GetColor is made with a color number
  82. that exceeds the size of the view's palette. For example, let's see what
  83. happens when we insert a TListBox into a TWindow, rather than a TDialog.
  84. (Note: The TV Guide says that TListBox's palette maps onto the application
  85. palette. This is incorrect; it actually maps onto TDialog's palette.) TListBox
  86. has a five-entry palette which maps onto entries 26 through 29 in its owner's
  87. palette. Well, lo and behold, a TWindow has only eight entries in its
  88. palette--obtaining the 26th entry is impossible. In this situation, GetColor
  89. returns the flashing white on red color to signal the error.
  90.  
  91. Here is a list of all of the entries in TApplication's palette, along with the
  92. objects that use them:
  93.  
  94.  1 Background (DeskTop)
  95.  2 Text Normal (Menu)
  96.  3 Text Disabled (Menu)
  97.  4 Text Shortcut (Menu)
  98.  5 Selected Normal (Menu)
  99.  6 Selected Disabled (Menu)
  100.  7 Selected Shortcut (Menu)
  101.  8 Frame Passive (Blue Window)
  102.  9 Frame Active (Blue Window)
  103. 10 Frame Icon (Blue Window)
  104. 11 ScrollBar Page (Blue Window)
  105. 12 ScrollBar Reserved (Blue Window)
  106. 13 Scroller Normal Text (Blue Window)
  107. 14 Scroller Selected Text (Blue Window)
  108. 15 Reserved (Blue Window)
  109. 16 Frame Passive (Cyan Window)
  110. 17 Frame Active (Cyan Window)
  111. 18 Frame Icon (Cyan Window)
  112. 19 ScrollBar Page (Cyan Window)
  113. 20 ScrollBar Reserved (Cyan Window)
  114. 21 Scroller Normal Text (Cyan Window)
  115. 22 Scroller Selected Text (Cyan Window)
  116. 23 Reserved (Cyan Window)
  117. 24 Frame Passive (Gray Window)
  118. 25 Frame Active (Gray Window)
  119. 26 Frame Icon (Gray Window)
  120. 27 ScrollBar Page (Gray Window)
  121. 28 ScrollBar Reserved (Gray Window)
  122. 29 Scroller Normal Text (Gray Window)
  123. 30 Scroller Selected Text (Gray Window)
  124. 31 Reserved (Gray Window)
  125. 32 Frame Passive (Dialog)
  126. 33 Frame Active (Dialog)
  127. 34 Frame Icon (Dialog)
  128. 35 ScrollBar Page (Dialog)
  129. 36 ScrollBar Controls (Dialog)
  130. 37 StaticText (Dialog)
  131. 38 Label Normal (Dialog)
  132. 39 Label Highlight(Dialog)
  133. 40 Label Shortcut (Dialog)
  134. 41 Button Normal (Dialog)
  135. 42 Button Default (Dialog)
  136. 43 Button Selected (Dialog)
  137. 44 Button Disabled (Dialog)
  138. 45 Button Shortcut (Dialog)
  139. 46 Button Shadow (Dialog)
  140. 47 Cluster Normal (Dialog)
  141. 48 Cluster Selected (Dialog)
  142. 49 Cluster Shortcut (Dialog)
  143. 50 InputLine Normal (Dialog)
  144. 51 InputLine Selected (Dialog)
  145. 52 InputLine Arrows (Dialog)
  146. 53 History Arrow (Dialog)
  147. 54 History Sides (Dialog)
  148. 55 HistoryWindow ScrollBar page (Dialog)
  149. 56 HistoryWindow ScrollBar controls (Dialog)
  150. 57 ListViewer Normal (Dialog)
  151. 58 ListViewer Focused (Dialog)
  152. 59 ListViewer Selected (Dialog)
  153. 60 ListViewer Divider (Dialog)
  154. 61 InfoPane (Dialog)
  155. 62 Reserved (Dialog)
  156. 63 Reserved (Dialog)
  157.  
  158. What about changing colors in Turbo Vision? If all you want to do is change
  159. the color of all instances of an object, say, by making all of your TButtons
  160. cyan instead of green, you've got it easy. You just change the appropriate
  161. entries in TApplication's palette (41 through 46), and you're set.
  162.  
  163. That was easy. Now, what about creating a new, unique view which is unlike any
  164. predefined Turbo Vision objects? How will we color it? Let's say we want to
  165. insert our new view (call it a TNewView) into a TDialog, and we want to use
  166. two different colors, one for normal text and one for highlighted text. First,
  167. we add two entries to TApplication's palette (numbers 64 and 65) that will
  168. correspond to the two colors used by our new view. For the purposes of this
  169. example, we'll say we want blue on light gray ($71) for normal text and light
  170. green on light gray ($7A) for highlighted text (assuming a color monitor). Our
  171. TApplication palette will now look like this:
  172.  
  173.   CColor =
  174.         #$71#$70#$78#$74#$20#$28#$24#$17#$1F#$1A#$31#$31#$1E#$71#$00 +
  175.     #$37#$3F#$3A#$13#$13#$3E#$21#$00#$70#$7F#$7A#$13#$13#$70#$7F#$00 +
  176.     #$70#$7F#$7A#$13#$13#$70#$70#$7F#$7E#$20#$2B#$2F#$78#$2E#$70#$30 +
  177.     #$3F#$3E#$1F#$2F#$1A#$20#$72#$31#$31#$30#$2F#$3E#$31#$13#$00#$00 +
  178.     #$71#$7A;  { <- these last two are the new entries }
  179.  
  180. We must make similar changes in the black & white and monochrome palettes, of
  181. course. Next, since we will be inserting TNewView into a TDialog, we need to
  182. override TDialog's GetPalette method so that it will supply GetColor with the
  183. proper palette:
  184.  
  185.   const
  186.     CNewDialog = CDialog + #64#65;
  187.  
  188.   type
  189.     TNewDialog = object (TDialog)
  190.       function GetPalette: PPalette; virtual;
  191.      end;
  192.    .
  193.    .
  194.    .
  195.   function TNewDialog.GetPalette: PPalette;
  196.  
  197.   const
  198.     P: String[Length (CNewDialog)] = CNewDialog;
  199.  
  200.   begin
  201.   GetPalette := @P;
  202.   end;
  203.  
  204. Since we added our two new colors to the end of the standard TDialog palette,
  205. which contains 32 entries, they will be the 33rd and 34th entries in
  206. TNewDialog's palette. Now we have to define our TNewView so that it maps onto
  207. the 33rd and 34th entry of its owner's palette:
  208.  
  209.   const
  210.     CNewView = #33#34;
  211.  
  212.   type
  213.     TNewView = object (TView)
  214.       function GetPalette: PPalette; virtual;
  215.        .
  216.       .
  217.       .
  218.       end;
  219.  
  220.   function TNewView.GetPalette: PPalette;
  221.  
  222.   const
  223.     P: String[Length (CNewView)] = CNewView;
  224.  
  225.   begin
  226.   GetPalette := @P;
  227.   end;
  228.  
  229. There. That wasn't so bad, was it? When TNewView's Draw method asks for color
  230. number 1, it will get color number 64 from TApplication's palette; similarly,
  231. color number 2 leads to TApplication's color number 65. If we ever want to
  232. change the colors of our TNewView object, we simply change the entries in
  233. TApplication's palette.
  234.  
  235. Okay, let's try something a bit trickier. Let's say we want to insert a view
  236. into an owner which is not of the "correct" type. We already know that unless
  237. we modify the palettes and associated methods, the colors will come out wrong.
  238. The most general solution to the problem is to define a new object type, as in
  239. the previous example. Thus, if we wanted to insert a TButton into a TWindow,
  240. we would define a descendant of TButton (called TWindowButton, perhaps) and
  241. follow the same steps we performed above to give it a set of colors to use.
  242.  
  243. In some cases, we don't need to add to TApplication's palette. In the previous
  244. example, if all we want to do is put a button in a window, and we want the
  245. button to look just like an ordinary TButton inserted into a TDialog, we can
  246. use the same TApplication palette entries (41 through 46):
  247.  
  248.   const
  249.     CNewWindow = CGrayWindow + #41#42#43#44#45#46;
  250.     CWindowButton = #9#10#11#12#13#13#13#14;
  251.  
  252.   type
  253.     TNewWindow = object (TWindow)
  254.       function GetPalette: PPalette; virtual;
  255.      end;
  256.  
  257.     TWindowButton = object (TButton)
  258.       function GetPalette: PPalette; virtual;
  259.       end;
  260.  
  261. The GetPalette method code is analogous to that of the previous example. Now,
  262. when TWindowButton.Draw asks for color number 2, it is mapped to TNewWindow's
  263. color number 10, which is mapped to TApplication's color number 42, just as if
  264. it had been a TButton inserted into a TDialog. Note that I used CGrayWindow as
  265. the basis for CNewWindow's palette. Since a TButton is normally inserted into
  266. a TDialog, two of its colors (44 and 46) use a gray background. If you wanted
  267. to put buttons into cyan or blue windows, you would need to use the more
  268. general method of adding to TApplication's palette, as in the previous
  269. example.
  270.  
  271. Last but not least, what about objects which can be instantiated with one of
  272. several palettes? TWindow is a good example of this type of object; you can
  273. have windows with blue, gray, or cyan color schemes. One of TWindow's fields
  274. (Palette) is used to indicate which color scheme GetPalette should return.
  275. TWindow.GetPalette might look something like this:
  276.  
  277.   function TWindow.GetPalette: PPalette;
  278.  
  279.   const
  280.     PGray: string[Length (CGrayWindow)] = CGrayWindow;
  281.     PCyan: string[Length (CCyanWindow)] = CCyanWindow;
  282.     PBlue: string[Length (CBlueWindow)] = CBlueWindow;
  283.  
  284.   begin
  285.   case Palette of
  286.     wpGrayWindow: GetPalette = @PGray;
  287.     wpCyanWindow: GetPalette = @PCyan;
  288.     wpBlueWindow: GetPalette = @PBlue;
  289.     end;
  290.   end;
  291.  
  292. You can use the same technique with any objects of your own devising.
  293.  
  294. Well, that's about it for Turbo Vision palettes. Are you thoroughly confused
  295. yet? Just remember: figuring out what color a view is going to be drawn with
  296. is as simple as tracing the color mapping up the ownership hierarchy, until
  297. you reach the TApplication object.
  298.  
  299. Please direct comments or suggestions to Steve Schafer [71121,1771].
  300.